#include <vcl.h>
#pragma hdrstop

#include <EIC.h>
#include "CEdit.h"
#include "CMemo.h"
#include "CGBox.h"
#include "CGRadio.h"
#include "CEditNum.h"
#include "CEditMon.h"
#include "CEditCpt.h"
#include "CDate.h"
#include "CCheckB.h"
#include "CRadBtn.h"
#include "CComboBx.h"
#include "CListBox.h"

#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck est utilisé pour être sûr que les composants créés ne
// contiennent aucune fonction virtuelle pure.
//
static inline void ValidCtrCheck(CCustomEdit *)
{
 new CCustomEdit(NULL);
}


namespace Cedit
{
void __fastcall PACKAGE Register()
{
 TComponentClass classes[1] = {__classid(CEdit)};
 RegisterComponents("EIC Ctrlstd", classes, 0);
}
}

//////////////////////////////////////
//
// CCustomEdit
//
// Fonction: Constructeur de la Classe CCustomEdit
//
// P.E.: AUCUN
//
// P.S.: AUCUN
//
//////////////////////////////////////
__fastcall CCustomEdit::CCustomEdit( TComponent* pOwner)
: TCustomMemo( pOwner)
{
    FFlechesChangentFocus       = true;
    FLibelleFont                 = 0;
    FReadOnly                   = false;
    FTabStop                    = true;
    inherited::AutoSize         = true;
    inherited::AutoSelect       = true;
    inherited::ReadOnly         = false;
    inherited::TabStop          = true;
    inherited::Visible          = true;
    inherited::WordWrap         = false;
    inherited::WantReturns      = false;
    inherited::ShowHint         = false;
    Height                      = 21;
    Width                       = 105;

    FSizeEsp                    = ECART_LIBEL_EDIT;

    ASSERT( m_feFiltres == FiltresEdit()); // Aucun Filtre par défaut
    m_uMaxChars                  = 0;               // Saisie illimitée
    m_pfnOnIllegalChar           = NULL;            // Pas de gestion des caractères rejetés par les filtres
    m_pfnOnIllegalPaste          = NULL;            // Pas de gestion de "collage" illégal
    m_pfnOnEstCorrectementRempli = NULL;

    try
        {
        FLibelleFont            = new TFont();
        FLibelleFont->Assign( Font );
        LLibelle                = new TLabel( this );
        LLibelle->Transparent   = true;
        LLibelle->FocusControl  = this;
        FLibelleFont->OnChange  = LibelleFontChange;
        }

   catch(...)
        {
        }
} /* CCustomEdit::CCustomEdit() */



__fastcall CCustomEdit::~CCustomEdit()
{
  delete FLibelleFont;
  FLibelleFont = 0;
}



/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*\
+++++++++++++ CCustomEdit::IsStringValid() +++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+                                                                              +
+    Cette procédure membre permet de savoir si une chaîne de texte est valide +
+ pour le control (i.e. si tous ses caractères sont valides par rapport aux    +
+ filtres actifs sur la saisie).                                               +
+                                                                              +
+ Paramètres :                                                                 +
+   pcsz : Chaîne à tester                                                     +
+                                                                              +
+ Retour :                                                                     +
+   TRUE si la chaîne est valide; FALSE sinon.                                 +
+                                                                              +
+ Note : Une chaîne vide est valide.                                           +
\*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
bool __fastcall CCustomEdit::IsStringValid( const char* pcsz)
const
{
 char c; // Un caractère de la chaîne

 if( m_feFiltres == FiltresEdit())
 { // Pas de filtre actif en saisie
   return( true);
 }
 else
   for(;;)
     switch( c = *pcsz++)
     {
       case '\0' :
         return( true); // Tous les caractères de la chaîne sont valides

       case ' '  :
         if( !m_feFiltres.Contains( feBlanc)) return( false);
         continue;

       default   :
         if( ( ( c >= 'A') && ( c <= 'Z')) || ( ( c >= 'a') && ( c <= 'z')))
           if( !m_feFiltres.Contains( feAlpha))     return( false); else continue;
         if( ( c >= '0') && ( c <= '9'))
           if( !m_feFiltres.Contains( feNumerique)) return( false); else continue;
         if( c >= 0x20)
         { // Caractère invalide (lettre accentuée u signe mathématique
           return( false);
         }
         else
         { // Tous les caractères de contrôle sont acceptés
           continue;
         }
     }
} /* CCustomEdit::IsStringValid() */


/******************************************************************************\
************* CCustomEdit::SolveSelection() ************************************
********************************************************************************
*                                                                              *
*    Cette fonction retourne le texte du control sans la sélection courante.   *
*                                                                              *
* Paramètres :                                                                 *
*   dwCaretPos0 : Retourne la position, en base zéro, du caret dans le control *
*                 lorsque la sélection sera effacée.                           *
*                                                                              *
* Retour :                                                                     *
*   Le texte du control sans sa sélection.                                     *
*                                                                              *
* Attention : Si le control a sa propriété AutoSelect à true et qu'il n'a pas  *
*             le focus, la chaîne retournée est toujours vide.                 *
\******************************************************************************/
AnsiString __fastcall CCustomEdit::SolveSelection( DWORD& dwCaretPos0)
{
 DWORD dwStart, dwEnd;


 /////////////////////////////
 // Lecture de la sélection //
 /////////////////////////////
 Perform( EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
 ASSERT( dwStart <= dwEnd);
 dwCaretPos0 = dwStart;

 if( dwStart != dwEnd)
 { // Une sélection de texte existe
   // => Destruction de la sélection dans la valeur de retour
   AnsiString strText( Text);

   strText.Delete( dwStart + 1, dwEnd - dwStart);
   return( strText);
 }
 else
 { // Pas de sélection dans le control
   // => Retourne tout le texte
   return( Text);
 }
} /* CCustomEdit::SolveSelection() */


//////////////////////////////////////
//
// SetEnabled
//
// Fonction: Initialise Enabled
//
// P.E.: Enabled
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCustomEdit::SetEnabled( bool bEnabled )
    {
    inherited::Enabled      = bEnabled;
    if( LLibelle )
        LLibelle->Enabled   = bEnabled;

    if( bEnabled )
        SetReadOnly( inherited::ReadOnly );
    else
        RafraichirFond(this);
    }



//////////////////////////////////////
//
// SetLibelle
//
// Fonction: Initialise le Libelle
//
// P.E.: le Libelle
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCustomEdit::SetLibelle( const AnsiString  aLibelle )
    {
    FLibelle = aLibelle;

   if( LLibelle )
        {
        LLibelle->Visible    = Visible;
        LLibelle->Enabled    = Enabled;
        LLibelle->Parent     = Parent;
        LLibelle->Font       = LibelleFont;
        LLibelle->Caption    = FLibelle;
        LLibelle->Alignment  = taRightJustify;
        ReplaceLibelle();
        }
    }



//////////////////////////////////////
//
// SetLibelleFont
//
// Fonction: Initialise la fonte du Libelle
//
// P.E.: LibelleFont
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCustomEdit::SetLibelleFont( TFont *FFont )
    {
    FLibelleFont->Assign( FFont );
    }

//////////////////////////////////////
//
// SetReadOnly
//
// Fonction: Initialise l'Edit en lecture seule ou en lecture/ecriture
//           Repaint le fond en fonction de sa valeur
//
// P.E.: ReadOnly
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCustomEdit::SetReadOnly( bool bReadOnly )
    {
    FReadOnly = bReadOnly;
    inherited::ReadOnly =  bReadOnly;
    inherited::TabStop = bReadOnly ? false : FTabStop;

    RafraichirFond(this);
    }



//////////////////////////////////////
//
// SetSizeEsp
//
// Fonction: Initialise la taille de l'espace entre le Libelle et l'Edit
//
// P.E.: La taille
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCustomEdit::SetSizeEsp( int iSizeEsp )
    {
    FSizeEsp = iSizeEsp;

    if( LLibelle )
      ReplaceLibelle();
    }



//////////////////////////////////////
//
// SetVisible
//
// Fonction: Initialise Visible
//
// P.E.: Visible
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCustomEdit::SetVisible( bool bVisible )
    {
    inherited::Visible    = bVisible;

    if( LLibelle )
        LLibelle->Visible    = bVisible;
    }

void __fastcall CCustomEdit::SetShowHint( bool bShowHint )
{
  inherited::ShowHint    = bShowHint;
  RafraichirFond(this);
}

void __fastcall CCustomEdit::SetHint(AnsiString aHint)
{
  inherited::Hint = aHint;
  RafraichirFond(this);
}


void __fastcall CCustomEdit::SetTabStop( bool bTabStop)
{
  FTabStop = bTabStop;
  inherited::TabStop = bTabStop && !ReadOnly;
}

/*----------------------------------------------------------------------------*\
---------------- SetFiltres() --------------------------------------------------
--------------------------------------------------------------------------------
-                                                                              -
-    Cette procédure permet de modifier les filtres de saisie à appliquer au   -
- control.                                                                     -
-                                                                              -
- Paramètres :                                                                 -
-   feFiltres : Nouveaux filtres à assigner au control.                        -
-                                                                              -
- Note : le filtre "feTotal" est axclusif avec tout filtre particulier i.e.    -
-        l'application du filtre "feTotal" supprime tous les autres filtres    -
-        (ainsi, tous les caractères seront redirigés vers l'événement         -
-        OnIllegalChar()) et l'application d'un filtre autre que "feTotal"     -
-        supprime le filtre "feTotal".                                         -
\*----------------------------------------------------------------------------*/
void __fastcall CCustomEdit::SetFiltres( const FiltresEdit feFiltres)
{
 if( feFiltres.Contains( feTotal))
 { // Le filtre "feTotal" est exclusif avec (et prioritaire sur) tout autre filtre
   ( m_feFiltres.Clear()) << feTotal;
 }
 else
 { // Un/Des filtre(s) particulier(s) supprime(nt) obligatoirement le filtre "feTotal"
   m_feFiltres = feFiltres;
 }
} /* CCustomEdit::SetFiltres() */

bool __fastcall CCustomEdit::EstCorrectementRempliDefault( void)
{
  return( !Text.IsEmpty());
}
void __fastcall CCustomEdit::SetObligatoire( bool bObligatoire)
{
  FObligatoire = bObligatoire;
  RafraichirFond(this);
}

void __fastcall CCustomEdit::SetBleuSiHint( bool bBleuSiHint)
{
  FBleuSiHint = bBleuSiHint;
  RafraichirFond(this);
}

//////////////////////////////////////
//
// GetEnabled
//
// Fonction:
//
// P.E.: AUCUN
//
// P.S.: Enabled
//
//////////////////////////////////////
bool __fastcall CCustomEdit::GetEnabled()
    {
    return( inherited::Enabled );
    }



TFont * __fastcall CCustomEdit::GetLibelleFont() const
    {
    return( FLibelleFont );
    }



//////////////////////////////////////
//
// GetReadOnly
//
// Fonction: Retourne la valeur de ReadOnly
//
// P.E.: AUCUN
//
// P.S.: ReadOnly
//
//////////////////////////////////////
bool __fastcall CCustomEdit::GetReadOnly() const
    {
    return( inherited::ReadOnly );
   }



//////////////////////////////////////
//
// GetVisible
//
// Fonction: Retourne l'etat Visible
//
// P.E.: AUCUN
//
// P.S.: Visible
//
//////////////////////////////////////
bool __fastcall CCustomEdit::GetVisible() const
    {
    return( inherited::Visible );
    }

bool __fastcall CCustomEdit::GetShowHint() const
{
  return( inherited::ShowHint );
}

AnsiString __fastcall CCustomEdit::GetHint()
{
  return inherited::Hint;
}


bool __fastcall CCustomEdit::GetTabStop() const
{
  return FTabStop;
}

//////////////////////////////////////
//
// LibelleFontChange
//
// Fonction: Initialise la fonte du libelle avec la nouvelle fonte choisie
//
// P.E.:
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCustomEdit::LibelleFontChange( TObject *Sender )
    {
    if( LLibelle )
        {
        LLibelle->Font->Assign( FLibelleFont );
        ReplaceLibelle();
        }
    }

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
AnsiString __fastcall CCustomEdit::GetText() 
{
return inherited::Text.Trim();
}

/*******************************************************************************

Fonction :

Paramètres d'entrée :

Paramètres de sortie :

Valeur retournée :
*******************************************************************************/
void __fastcall CCustomEdit::SetText(AnsiString aText)
{
inherited::Text = aText;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*\
+++++++++++++ CCustomEdit::WMSetText() +++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+                                                                              +
+    Cette méthode permet d'initialiser le texte du control en ignorant les    +
+ espaces ( ' ') de début et de fin.                                           +
+                                                                              +
+ Paramètres :                                                                 +
+   Msg.Text : Texte à afficher dans le control.                               +
+                                                                              +
+ Retour :                                                                     +
+   Msg.Result : TRUE si le texte a bien pu être initialisé; FALSE sinon.      +
+                                                                              +
+ Note : Si le texte (épuré de ses ' ' de début et de fin) est plus long que   +
+        la limite autorisée, les caractères en trop sont ignorés et cela      +
+        n'affecte pas le sens de la valeur de retour de la fonction.          +
\*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void __fastcall CCustomEdit::WMSetText( Messages::TWMSetText& Msg)
{
 UINT  uNbCar; // Longueur du texte épuré des caractères blancs initiaux et finaux
 char* pc;     // Un caractère à afficher


 ///////////////////////////////////////////////////
 // Vérification de la possibilité de l'opération //
 ///////////////////////////////////////////////////
 if( ( pc = Msg.Text) == NULL)
 { // Rien à afficher
   // => On laisse faire la VCL
   inherited::Dispatch( &Msg);
   return;
 }


 /////////////////////////////////////
 // Préparation du texte à afficher //
 /////////////////////////////////////
 // On ignore les blancs de début
 while( *pc == ' ')
   pc++;

 // Allocation et copie du texte ainsi pré-nettoyé
 AnsiString str( pc);

 // On ignore les ' ' terminaux dans la copie du texte
 if( ( uNbCar = str.Length()) > 0)
   for( pc = str.c_str() + uNbCar; uNbCar; )
    if( *--pc == ' ')
     {
       *pc = '\0';
       uNbCar--;
     }
    else
       break;

 // Vérification de la longueur du texte à afficher
 if( ( m_uMaxChars != 0) && ( uNbCar > m_uMaxChars))
 {
   uNbCar -= m_uMaxChars;
   memset( pc - uNbCar + 1, '\0', uNbCar);
 }

 // Sauvegarde du buffer d'origine
 pc = Msg.Text;

 // Affichage du texte copié
 Msg.Text = str.c_str();
 inherited::Dispatch( &Msg);

 // Restitution du buffer d'origine
 Msg.Text = pc;

 RafraichirFond(this);

 } /* CCustomEdit::WMSetText() */


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*\
+++++++++++++ CCustomEdit::EMLimitText() +++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+                                                                              +
+    Cette méthode permet de fixer la taille maximale des données affichées,   +
+ saisies ou initialisées du control.                                          +
+                                                                              +
+ Paramètres :                                                                 +
+   Msg.uMaxChars : Taille maximale autorisée (0 = taille illimitée).          +
+                                                                              +
+ Note : Cette méthode tronque le texte déjà affiché dans le control si cela   +
+        est nécessaire.                                                       +
\*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void __fastcall CCustomEdit::EMLimitText( TEMLimitText& Msg)
{
 bool bDoTrunc; // TRUE s'il faut tronquer le texte existant dans le control


 /////////////////////////////
 // Changement de la limite //
 /////////////////////////////
 if( ( Msg.uMaxChars != 0) &&
    ( ( m_uMaxChars == 0) ||   // On assigne une limite alors qu'il n'y en avait pas
      ( Msg.uMaxChars < m_uMaxChars))) // On réduit la limite existante
   bDoTrunc = TRUE;
 else
   bDoTrunc = FALSE;

 m_uMaxChars = Msg.uMaxChars;

 if( bDoTrunc)
 { // La nouvelle limite de texte est inférieure à la précédente
   // => on réaffiche le texte existant en le tronquant
   ::SetWindowText( Handle, Text.c_str());
   Refresh();
 }

 inherited::Dispatch( &Msg);
} /* CCustomEdit::EMLimitText() */


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*\
+++++++++++++ CCustomEdit::WMChar() ++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+                                                                              +
+    Cette méthode permet de filtrer les caractères saisis dans le control.    +
+                                                                              +
+ Paramètres :                                                                 +
+   Msg.CharCode : Code caractère de la touche                                 +
+   Msg.KeyData  : Repeat count, Scan code, contexte...                        +
+                                                                              +
+ Retour :                                                                     +
+   Msg.Result : 0 si le message est traité.                                   +
+                                                                              +
+ Notes : * Si un caractère illégal est détecté, il peut quand même être       +
+           accepté via l'événement OnIllegalChar().                           +
+         * Les caractères de contrôle ( ASCII < 32 et != VK_BACK) sont        +
+           toujours acceptés.                                                 +
+         * Dans tous les cas, le caractère ' ' est refusé en début de saisie. +
\*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void __fastcall CCustomEdit::WMChar( Messages::TWMChar& Msg)
{
 FiltreEdit feChar;  // Filtre auquel le caractère appartient
 bool       bAccept; // TRUE si le caractère à traiter est illégal mais quand même accepté


 if ( Msg.CharCode==VK_BACK) goto lblNoTrait;

 if( ( Msg.CharCode >= 32) || ( Msg.CharCode == VK_BACK))
 { ////////////////////////////////////////////////////////////
   // Détermination du filtre auquel le caractère appartient //
   ////////////////////////////////////////////////////////////
   if( ( ( Msg.CharCode >= 'A') && ( Msg.CharCode <= 'Z')) ||
      ( ( Msg.CharCode >= 'a') && ( Msg.CharCode <= 'z')))
   { // Caractère alphabéthique
    feChar = feAlpha;
   }
   else if( ( Msg.CharCode >= '0') && ( Msg.CharCode <= '9'))
   { // Caractère numérique
    feChar = feNumerique;
   }
   else if( Msg.CharCode == ' ')
   {
     if( !SelStart)
    { // Le caret est à la 1ère position : un ' ' est interdit en début de saisie
       MessageBeep( 0xFFFFFFFF);
       Msg.Result = 0;
       return;
     }
     else
      feChar = feBlanc;
   }
   else
   { // Autre caractère (lettre accentuée ou signe mathématique)
     feChar = feTotal;
   }


   /////////////////////////////
   // Traitement du caractère //
   /////////////////////////////
   if( m_feFiltres.Contains( feTotal) ||     // Tous les caractères doivent être filtrés OU...
      ( ( m_feFiltres != FiltresEdit()) &&  //   ...des filtres existent sur ce control...
         ( !m_feFiltres.Contains( feChar)))) //   ...et le caractère frappé ne tombe dans aucun filtre
   { // Le caractère est interdit
    // => Peut-on quand-même l'accepter ?
     bAccept = false;
     if( m_pfnOnIllegalChar)
     { // Conversion pour la casse (car le caractère frappé n'est pas encore converti par Windows)
       switch( CharCase)
       { case ecLowerCase : Msg.CharCode = (Word)::CharLower( (LPTSTR)Msg.CharCode); break;
         case ecUpperCase : Msg.CharCode = (Word)::CharUpper( (LPTSTR)Msg.CharCode); break;
       }

       // Traitement de l'illégalité
       m_pfnOnIllegalChar( this, Msg.CharCode, bAccept);
     }
     if( !bAccept)
     { // Caractère illégal non accepté
       MessageBeep( 0xFFFFFFFF);
      Msg.Result = 0;
       return;
     }
   }
 }

 // Le caractère est accepté
lblNoTrait:
 inherited::Dispatch( &Msg);
} /* CCustomEdit::WMChar() */


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*\
+++++++++++++ CCustomEdit::WMPaste() +++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+                                                                              +
+    Cette méthode permet de coller (ou d'interdire le collage selon le type   +
+ du control) les données du presse-papiers dans le control.                   +
+                                                                              +
+ Note : Si les données du presse-papiers sont illégales elles peuvent quand   +
+        même être acceptées via l'événement OnIllegalPaste(); cet événement   +
+        peut provoquer une modification des données du presse-papier.         +
\*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void __fastcall CCustomEdit::WMPaste( Messages::TWMPaste& Msg)
{
 HGLOBAL hglbClipText; // Handle du texte du presse-papiers
 char*   pszClipText;  // Texte du presse-papiers
 bool    bIsPastable;  // TRUE si le presse-papiers peut être collé


 ////////////////////////////////////////
 // Lecture du texte du presse-papiers //
 ////////////////////////////////////////
 // Ouverture du presse-papiers //
 if( !::OpenClipboard( Handle))
 { // Erreur: ouverture du presse-papier impossible
   // => On suppose, sans avertir l'utilisateur par un beep, que ce qu'il contient est invalide
   return;
 }

 // Lecture du texte du presse-papiers //
 bIsPastable = false;
 if( ( hglbClipText = ::GetClipboardData( CF_TEXT)) != NULL)
 { // Du texte est bien présent dans le presse-papiers
   if( ( pszClipText = (char*)::GlobalLock( hglbClipText)) != NULL)
   {
   AnsiString aNewText;
   int iPosSautDeLigne;
   aNewText = pszClipText;

    //Suppression de tous le texte qui suite le premier saute de ligne
    if ((iPosSautDeLigne = aNewText.Pos("\r\n")) != 0)
       aNewText.Delete(iPosSautDeLigne, aNewText.Length());

    // Ce texte est-il valide ?
    if( IsStringValid( aNewText.c_str()))
     { // Le texte du presse-papiers est légal
       // => Il va être collé normalement
       bIsPastable = TRUE;
     }
    else if( m_pfnOnIllegalPaste)
     { // Le texte du presse-papiers est illégal
       // => Peut-il être quand même collé (après avoir éventuellement subi des modifications via OnIllegalPaste) ?

      m_pfnOnIllegalPaste(this, aNewText, bIsPastable);
     }

     if( bIsPastable)
     { // Le texte a été modifié
       // => Modification éventuelle du presse-papiers
       if( strcmp(aNewText.c_str(), pszClipText))
       { // Modification du texte du presse-papiers avec le nouveau texte valide
       bIsPastable = false;

         if(::GlobalUnlock( hglbClipText) == 0)
          if(::EmptyClipboard())
           if(( hglbClipText = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE, aNewText.Length() + 1)) != NULL)
            if(( pszClipText = (char*)::GlobalLock( hglbClipText)) != NULL)
         {
           strcpy( pszClipText, aNewText.c_str());
           if( ::GlobalUnlock( hglbClipText) == 0)
           if( ::SetClipboardData( CF_TEXT, hglbClipText))
             bIsPastable = true;
         }
       }
     }

     ::GlobalUnlock( hglbClipText);
   }

   if( !bIsPastable)
   { // Le texte du presse papiers est illégal et ne peut être collé
     // => Notification via un beep
    ::MessageBeep( -1);
   }
 }

 // Fermeture du presse-papiers //
 ::CloseClipboard();


 //////////////////////
 // Collage éventuel //
 //////////////////////
 if( bIsPastable)
   inherited::Dispatch( &Msg);
} /* CCustomEdit::WMPaste() */



//////////////////////////////////////
//
// WndProc
//
// Fonction: Capture les messages
//
// P.E.: Les messages
//
// P.S.: AUCUN
//
//////////////////////////////////////
void __fastcall CCustomEdit::WndProc( TMessage &Message )
   {
   switch( Message.Msg )
      {
      case WM_SETFOCUS:
         {
         if( !ComponentState.Contains( csDesigning ))
            {
            if( inherited::ReadOnly )
               {
               Message.Msg = WM_NULL;
               ::SetFocus( (HWND)Message.WParam );
               }

            else if( inherited::AutoSelect )
               SelectAll();
            }
         break;
         }

      case WM_WINDOWPOSCHANGED:
         {
         if( LLibelle )
            {
            inherited::WndProc( Message );
            ReplaceLibelle();
            Message.Msg     = WM_NULL;
            }
         break;
         }

      case WM_ENABLE:
         {
         Enabled             = (bool)Message.WParam;
         break;
         }

      case WM_READONLY:
         {
         ReadOnly            = (bool)Message.WParam;
         break;
         }
      }
   inherited::WndProc( Message );
   }



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CCustomEdit::KeyDown(Word &Key, Classes::TShiftState Shift)
   {
   TControl *CtrlLePlusProche    = NULL;

   if(    (Key == VK_RETURN    && Shift.Contains( ssCtrl ) && !dynamic_cast<CMemo*>(this))
      ||    (Key == VK_TAB       && Shift.Contains( ssCtrl ) && !dynamic_cast<CMemo*>(this)))
      {
      iOldSelPos       = SelStart;
      iOldSelLength    = SelLength;
      aOldText       = Text;
      Key            = VK_CANCEL;
      }
   else if(Key == VK_TAB       && Shift.Contains( ssCtrl ) && !dynamic_cast<CMemo*>(this))
      Key            = VK_CANCEL;
   else
      {
      if(FFlechesChangentFocus && (Key == VK_DOWN ||Key == VK_UP))
         {
         CtrlLePlusProche = FindControlUpOrDown( Parent, this, Key );
         if( CtrlLePlusProche != NULL )
            ::SetFocus( ((TWinControl*)CtrlLePlusProche)->Handle );
         Key = VK_CANCEL;
         }
      inherited::KeyDown( Key, Shift );
      }
   }



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CCustomEdit::KeyUp(Word &Key, Classes::TShiftState Shift)
   {
   if( Key == VK_RETURN && Shift.Contains( ssCtrl ) && !dynamic_cast<CMemo*>(this))
      {
      Text       = aOldText;
      SelStart    = iOldSelPos;
      SelLength   = iOldSelLength;
      }

   inherited::KeyUp( Key, Shift );
   }

void __fastcall CCustomEdit::Change( void)
{
  RafraichirFond(this);
  inherited::Change();
}


////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
TControl * __fastcall CCustomEdit::FindControlUpOrDown( TWinControl *Parent, TWinControl *Ctrl, Word Key )
   {
   int       i                = 0;
   TRect       rLePlusProche       = Rect( 0, 1000, 1000, 0 );
   TWinControl *CtrlLePlusProche = NULL;
   TWinControl *CtrlCurr         = NULL;
   TWinControl *CtrlTmp = NULL;
   bool      bIsEICComponent;
   bool      bReadOnly         = false;
   bool bVisible;
   bool bEnabled;

   while (Parent->Parent && !dynamic_cast<TCustomForm*>(Parent))
      Parent = Parent->Parent;

   for (i=0 ; i< Parent->ComponentCount ; i++)
      {
      if ((CtrlCurr = dynamic_cast<TWinControl*>(Parent->Components[i])) == NULL)
         continue;

      bIsEICComponent = (AnsiString(CtrlCurr->ClassName()).Pos("C") == 1 );

      if( bIsEICComponent )
         {
         if( CtrlCurr->ClassNameIs(      "CRadioButton"))
            bReadOnly   = ((CRadioButton*)CtrlCurr)->ReadOnly;
         else if( CtrlCurr->ClassNameIs(   "CEdit"))
            bReadOnly   = ((CEdit*)CtrlCurr)->ReadOnly;
         else if( CtrlCurr->ClassNameIs(   "CEditNum"))
            bReadOnly   = ((CEditNum*)CtrlCurr)->ReadOnly;
         else if( CtrlCurr->ClassNameIs(   "CEditMontant"))
            bReadOnly   = ((CEditMontant*)CtrlCurr)->ReadOnly;
         else if( CtrlCurr->ClassNameIs(   "CDate"))
            bReadOnly   = ((CDate*)CtrlCurr)->ReadOnly;
         else if( CtrlCurr->ClassNameIs(   "CMemo"))
            bReadOnly   = ((CMemo*)CtrlCurr)->ReadOnly;
         else if( CtrlCurr->ClassNameIs(   "CEditCompte"))
            bReadOnly   = ((CEditCompte*)CtrlCurr)->ReadOnly;
         else if( CtrlCurr->ClassNameIs(   "CRadioButton"))
            bReadOnly   = ((CRadioButton*)CtrlCurr)->ReadOnly;
         else if( CtrlCurr->ClassNameIs(   "CCheckBox"))
            bReadOnly   = ((CCheckBox*)CtrlCurr)->ReadOnly;
         else if( CtrlCurr->ClassNameIs(   "CGroupBox"))
            bReadOnly   = ((CGroupBox*)CtrlCurr)->ReadOnly;
         else if( CtrlCurr->ClassNameIs(   "CGRadio"))
            bReadOnly   = ((CGRadio*)CtrlCurr)->ReadOnly;
         else if( CtrlCurr->ClassNameIs(   "CComboBox"))
            bReadOnly   = ((CComboBox*)CtrlCurr)->ReadOnly;
         else if( CtrlCurr->ClassNameIs(   "CListBox"))
            bReadOnly   = ((CListBox*)CtrlCurr)->ReadOnly;
         else
            continue;
         }

      else if(    dynamic_cast<TWinControl*>(CtrlCurr) == 0 || dynamic_cast<TCustomPanel*>(CtrlCurr) != 0
         ||       dynamic_cast<TCustomStaticText*>(CtrlCurr) != 0 )
         continue;

      //SI le composant ou l'un de ses parents est invisible, on passe au composant suivant.
      CtrlTmp = CtrlCurr;
      do
         {
         bVisible = CtrlTmp->Visible;
         bEnabled = CtrlTmp->Enabled;
         CtrlTmp = CtrlTmp->Parent;
         }
         while (CtrlTmp != Parent && bVisible && bEnabled);

      //SI le composant est différent du composant d'origine ET s'il est actif ET SI on peut s'y arrêter
      if(   (CtrlCurr != Ctrl && bEnabled && CtrlCurr->TabStop && bVisible)
         && (!bIsEICComponent ||(bIsEICComponent && !bReadOnly))
         && (   (CtrlCurr->ClientOrigin.x                   >= Ctrl->ClientOrigin.x     && CtrlCurr->ClientOrigin.x                   <= Ctrl->ClientOrigin.x     + Ctrl->Width    )
             || (CtrlCurr->ClientOrigin.x + CtrlCurr->Width >= Ctrl->ClientOrigin.x     && CtrlCurr->ClientOrigin.x + CtrlCurr->Width <= Ctrl->ClientOrigin.x     + Ctrl->Width    )
             || (Ctrl->ClientOrigin.x                       >= CtrlCurr->ClientOrigin.x && Ctrl->ClientOrigin.x                       <= CtrlCurr->ClientOrigin.x + CtrlCurr->Width)
             || (Ctrl->ClientOrigin.x + Ctrl->Width         >= CtrlCurr->ClientOrigin.x && Ctrl->ClientOrigin.x + Ctrl->Width         <= CtrlCurr->ClientOrigin.x + CtrlCurr->Width)))
         {
         // SI l'on veut monter ET que le composant est au-dessus de l'actif
         // OU SI l'on veut descendre ET que le composant est au-dessous de l'actif
         if(   Key == VK_UP   && CtrlCurr->ClientOrigin.y < Ctrl->ClientOrigin.y
            || Key == VK_DOWN && CtrlCurr->ClientOrigin.y > Ctrl->ClientOrigin.y)
            {
            //SI le composant est plus proche que l'ancien plus proche
            if(  Key == VK_UP   && CtrlCurr->ClientOrigin.y + CtrlCurr->Height > rLePlusProche.Bottom
              || Key == VK_DOWN && CtrlCurr->ClientOrigin.y < rLePlusProche.Top)
               {
               CtrlLePlusProche     = CtrlCurr;
               rLePlusProche.Left   = CtrlCurr->ClientOrigin.x;
               rLePlusProche.Top    = CtrlCurr->ClientOrigin.y;
               rLePlusProche.Right  = CtrlCurr->ClientOrigin.x + CtrlCurr->Width;
               rLePlusProche.Bottom = CtrlCurr->ClientOrigin.y + CtrlCurr->Height;
               }
            // SI le composant est à la même distance de l'ancien plus proche
            // Mais il est plus proche sur l'axe central
            else if( (   Key == VK_UP   && CtrlCurr->ClientOrigin.y + CtrlCurr->Height == rLePlusProche.Bottom
                      || Key == VK_DOWN && CtrlCurr->ClientOrigin.y == rLePlusProche.Top)
                  && (abs((Ctrl->ClientOrigin.x + Ctrl->Width/2.0) - (CtrlCurr->ClientOrigin.x + CtrlCurr->Width/2.0)) < abs((Ctrl->ClientOrigin.x + Ctrl->Width/2.0) - (rLePlusProche.Left + (rLePlusProche.Right - rLePlusProche.Left)/2.0))))
               {
               CtrlLePlusProche     = CtrlCurr;
               rLePlusProche.Left   = CtrlCurr->ClientOrigin.x;
               rLePlusProche.Top    = CtrlCurr->ClientOrigin.y;
               rLePlusProche.Right  = CtrlCurr->ClientOrigin.x + CtrlCurr->Width;
               rLePlusProche.Bottom = CtrlCurr->ClientOrigin.y + CtrlCurr->Height;
               }
            }
         }
      }
   return( CtrlLePlusProche );
   }


void __fastcall CCustomEdit::CreateParams(Controls::TCreateParams &Params)
{
//Bug : lorsque l'alignement du composant est à droite, et que le texte que l'on saisi
//sort du composant, il passe à la ligne suivante (car on dérive du TCustomMemo)
//Il faut donc supprimer le MultiLigne lié au CMemo.
//Sous 95, l'alignement à droite ne s'applique qu'au multiligne, on y laisse
//donc le bug.

inherited::CreateParams(Params);

// Annulation de cette correction car à la création de form contenant un CDate/CEditNum,
// le OnChange est lancé (injustifié)
//if (GetVersionDeWindows() != eWin95)
//   Params.Style &= ~ES_MULTILINE;
}


__fastcall CEdit::CEdit( TComponent* pOwner) : inherited( pOwner)
{
}
